package com.hxht.cmp.controller;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.hxht.cmp.common.Constants;
import com.hxht.cmp.common.enums.ResultCode;
import com.hxht.cmp.common.result.ResultResponse;
import com.hxht.cmp.entity.Role;
import com.hxht.cmp.entity.User;
import com.hxht.cmp.entity.UserRole;
import com.hxht.cmp.service.UserService;
import com.hxht.cmp.utils.MD5Utils;
import com.hxht.cmp.websocket.VodWebSocket;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

/**
 * @author alice on 2017/6/30 0030.
 * @version 1.0
 * @since 1.0
 */
@RestController
@RequestMapping("/oauth")
public class LoginController {
    private final Logger log = LoggerFactory.getLogger(LoginController.class);
    @Resource
    private UserService userService;

    /**
     * 网页登录
     *
     * @param username 用户名
     * @param password 密码
     * @return ResultResponse
     */
    @RequestMapping("/signIn")
    public ResultResponse signIn(String username, String password) {
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            return ResultResponse.failed(ResultCode.PARAMETER_NULL);
        }

        //状态不等于1，屏蔽内容
        if (Constants.SYSTEM_LOCKED == 1) {
            log.info("系统已锁定。用户[" + username + "]尝试登录。");
            return ResultResponse.init(1, "系统被锁定！", null);
        }
        Subject currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(true);
        String info;
        try {
            log.info("登录操作：尝试进行[username:" + username + ",password:" + password + ",token:" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE) + "]");
            currentUser.login(token);
            Session session = currentUser.getSession();
            log.info("登录操作：成功[username:" + username);
            Map<String, Object> resultMap = new HashMap<>();
            User user = (User) session.getAttribute("user");
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            List<UserRole> userRoleList = userService.getUserRole(userRole);
            List<String> list = new ArrayList<>();
            for (UserRole userRole1 : userRoleList) {
                list.add(userRole1.getRoleName());
            }
            for (Role role : Constants.ROLE_LIST) {
                if (list.contains(role.getAuthority())) {
                    session.setAttribute("indexUrl", role.getUrl());
                    resultMap.put("indexUrl", role.getUrl());
                }
            }
            if (ObjectUtils.isEmpty(resultMap.get("indexUrl"))) {
                return ResultResponse.init(1, "账户基础信息不完整！");
            }
            resultMap.put("userId", user.getUsername());
            resultMap.put("wsIP", Constants.CENTRAL_IP);
            resultMap.put("uuid", user.getUid());
            resultMap.put("courtUid", Constants.CENTRAL_COURT.getUid());
            resultMap.put("username", user.getUsername());
            resultMap.put("level", Constants.CENTRAL_COURT.getLevel());
            resultMap.put("courtName", Constants.CENTRAL_COURT.getName());
            return ResultResponse.init(0, "登录成功，欢迎您！正在跳转...", resultMap);
        } catch (UnknownAccountException uae) {
            log.info("登录操作：未知账户，验证未通过[username:" + username + "]");
            info = "用户名或密码不正确";
        } catch (IncorrectCredentialsException ice) {
            log.info("登录操作：错误的凭证，验证未通过[username:" + username + "]");
            info = "用户名或密码不正确";
        } catch (LockedAccountException lae) {
            log.info("登录操作：账户已锁定，验证未通过[username:" + username + "]");
            info = "您的账户已锁定.";
        } catch (ExcessiveAttemptsException eae) {
            log.info("登录操作：错误次数过多，验证未通过[username:" + username + "]");
            info = "用户名或密码错误次数过多,请在" + Constants.LOGIN_TIMEOUT + "分钟后再试.";
        } catch (AuthenticationException ae) {
            //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
            log.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下："+ ae.getMessage());
            info = "用户名或密码不正确";
        } finally {
            token.clear();
        }
        return ResultResponse.init(1, info);
    }

    @RequestMapping("/signOut")
    public ResultResponse logout() {
        SecurityUtils.getSubject().logout();
        return ResultResponse.success();
    }

    @RequestMapping("/vodUser")
    public ResultResponse selectVodUser(HttpServletRequest request, @RequestBody String jsonStr) {
        if (verify(request, jsonStr)) {
            return ResultResponse.success(VodWebSocket.selectVodUser());
        }
        return ResultResponse.failed(ResultCode.OAUTH_FAILED);
    }


    @RequestMapping("/lockUser")
    public ResultResponse lockUser(HttpServletRequest request, @RequestBody String jsonStr) {
        if (verify(request, jsonStr)) {
            try {
                Gson gson = new Gson();
                JsonObject jsonObject = gson.fromJson(jsonStr, JsonObject.class);
                VodWebSocket.messageLock("oauth/signOut", jsonObject.get("data").getAsJsonObject().get("uid").getAsString());
                return ResultResponse.success();
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        } else {
            return ResultResponse.failed(ResultCode.OAUTH_FAILED);
        }
        return ResultResponse.failed();
    }

    private Boolean verify(HttpServletRequest request, String jsonStr) {
        Gson gson = new Gson();
        JsonObject jsonObject = gson.fromJson(jsonStr, JsonObject.class);
        String appId = jsonObject.get("appId").getAsString();
        if (!Objects.equals("super", appId)) {
            return false;
        }
        Long timestamp = jsonObject.get("timestamp").getAsLong();
        String auth = request.getHeader("Authorization");
        if ((auth != null) && (auth.length() > 6)) {
            String headStr = auth.substring(0, 5).toLowerCase();
            if (Objects.equals(headStr, "basic")) {
                String temp = MD5Utils.code(appId + timestamp + "super");
                auth = auth.substring(6, auth.length());
                if (Objects.equals(temp, auth)) {
                    return true;
                }
            }
        }
        return false;
    }

}
